/**
	
                 Springs On Rails
                 Copyright [2007] [Sunny Liu]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.	
*/
package org.springonrails.parser;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import org.springonrails.model.Attribute;
import org.springonrails.model.Entity;
import org.springonrails.util.StringUtils;

public class EntityMapDomParser 
{
	private String mapLocation;
	private List<Entity> entities;
	private static Log log = LogFactory.getLog(EntityMapDomParser.class);
	private Properties additionalProperties = new Properties();
	
	
	public EntityMapDomParser(String mapLocation) {
		super();
		this.mapLocation = mapLocation;
		parse();	
	}
	
	public String getMapLocation() {
		return mapLocation;
	}
	public void setMapLocation(String mapLocation) {
		this.mapLocation = mapLocation;
	}
	public List<Entity> getEntities() 
	{		
		return entities;
	}
	
	public void setEntities(List<Entity> entities) {
		this.entities = entities;
	}
	
	
	
	public Properties getAdditionalProperties() {
		return additionalProperties;
	}

	public void setAdditionalProperties(Properties additionalProperties) {
		this.additionalProperties = additionalProperties;
	}
	

	protected void parse()
	{
		if (entities!=null) return;
		this.entities = new ArrayList<Entity>();
		
		try {
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			DocumentBuilder builder = factory.newDocumentBuilder();
			Document document = null;
			File f = new File(mapLocation);
			if(mapLocation!=null && f.exists()){				
				document = builder.parse( f );
			}else{
				log.warn("Entity Map file not found. " + f.getAbsolutePath());
				document = builder.parse( Thread.currentThread().getContextClassLoader().getResourceAsStream("/META-INF/typeMap.xml") );
			}
			
			NodeList metaElements = document.getDocumentElement().getElementsByTagName("meta");
			int mlen = metaElements.getLength();
			for (int k=0; k<mlen; k++) {
				Element el = (Element)metaElements.item(k);
				String prop = el.getTextContent();
				if(!StringUtils.isEmpty(prop)) 
					try{
						additionalProperties.load(new ByteArrayInputStream(prop.getBytes()));
					}catch(Exception ex){
						;
					}
			}
			
			NodeList entityElements = document.getDocumentElement().getElementsByTagName("entity");
			int len = entityElements.getLength();
			for(int i=0; i<len; i++){
				Element el = (Element)entityElements.item(i);
				Entity entity = new Entity();
				entity.setJavaName(StringUtils.matchEmptyReplaceWithNull(el.getAttribute("javaName")));
				entity.setTableName(StringUtils.matchEmptyReplaceWithNull(el.getAttribute("tableName")));
				entity.setViewLabel(StringUtils.matchEmptyReplaceWithNull(el.getAttribute("viewLabel")));				
				NodeList ms = el.getElementsByTagName("methods");
				if(ms!=null && ms.getLength()>0)
				{
					Element method = (Element)ms.item(0);
					entity.setMethods(StringUtils.matchEmptyReplaceWithNull(method.getTextContent()));
				}
				NodeList atts = el.getElementsByTagName("property");
				int count = atts.getLength();
				for(int j=0; j<count; j++){
					Element el1 = (Element)atts.item(j);
					Attribute att = new Attribute();
					att.setFormatString(StringUtils.matchEmptyReplaceWithNull(el1.getAttribute("formatString")));
					att.setJavaName(StringUtils.matchEmptyReplaceWithNull(el1.getAttribute("javaName")));
					att.setColumnName(StringUtils.matchEmptyReplaceWithNull(el1.getAttribute("columnName")));
					att.setViewLabel(StringUtils.matchEmptyReplaceWithNull(el1.getAttribute("viewLabel")));
					att.setAllowNull("true".equalsIgnoreCase(StringUtils.matchNullReplaceWithEmpty(el1.getAttribute("allowNull"))));
					att.setPrimaryKey("true".equalsIgnoreCase(StringUtils.matchNullReplaceWithEmpty(el1.getAttribute("primaryKey"))));
					att.setJavaType(StringUtils.matchEmptyReplaceWithNull(el1.getAttribute("javaType")));
					att.setSqlType(StringUtils.matchEmptyReplaceWithNull(el1.getAttribute("sqlType")));
					String attValue = StringUtils.matchEmptyReplaceWithNull(el1.getAttribute("foreignKey"));
					if(attValue!=null){
						String[] ns = attValue.split("[:]");
						att.setForeignKeyTableName(ns[0]);
						att.setForeignKeyColumnName(ns[1]);
					}					
					NodeList setter = el1.getElementsByTagName("set");
					if(setter!=null && setter.getLength()>0)
					{
						Element m = (Element)setter.item(0);
						att.setSetter(StringUtils.matchEmptyReplaceWithNull(m.getTextContent()));
					}
					NodeList getter = el1.getElementsByTagName("get");
					if(getter!=null && getter.getLength()>0)
					{
						Element m = (Element)getter.item(0);
						att.setGetter(StringUtils.matchEmptyReplaceWithNull(m.getTextContent()));
					}					
					entity.addAttribute(att);					
				}
				
				this.entities.add(entity);
			}			
		}  catch (Exception e) {			
			e.printStackTrace(System.out);
		}
		
		
	}
	
	
}
